Skip to content

feat(claw): add channel pairing step and load-settled gate to onboarding#1391

Merged
RSO merged 16 commits intomainfrom
RSO/pond-rugby
Mar 25, 2026
Merged

feat(claw): add channel pairing step and load-settled gate to onboarding#1391
RSO merged 16 commits intomainfrom
RSO/pond-rugby

Conversation

@RSO
Copy link
Copy Markdown
Contributor

@RSO RSO commented Mar 23, 2026

Summary

  • Add a channel pairing step to the KiloClaw onboarding flow for Telegram/Discord, including device pairing polling and a redesigned waiting state UI
  • Wire the gateway /ready endpoint through from controller → DO → tRPC → frontend to replace the hardcoded 60-second boot delay with real readiness polling
  • Gate the provisioning step on CPU load settling (os.loadavg()[0] < 0.1) in addition to gateway readiness — the controller now returns loadAverage and settled fields in the /ready response, preventing the frontend from advancing before boot CPU pressure subsides on the shared-cpu-2x instance

Verification

  • pnpm typecheck — passes
  • pnpm format — passes (pre-push hook ran format:check + lint + typecheck)
  • pnpm lint — passes

Visual Changes

telegram-pairing.mp4

Reviewer Notes

  • The controller change (kiloclaw/controller/src/routes/gateway.ts) requires a new Docker image deploy. Since this targets onboarding (new machines), they'll get the new image automatically.
  • GatewayReadyResponseSchema is already z.record(z.string(), z.unknown()) — the new loadAverage/settled fields flow through without schema changes.
  • The LOAD_SETTLED_THRESHOLD of 0.1 is calibrated for shared-cpu-2x (~6% of 2 physical cores). An idle system sits near 0; this threshold ensures boot work has fully subsided.
  • Error paths (gateway not running, fetch failure) also include loadAverage/settled, so the frontend naturally won't advance when things are broken.

RSO added 12 commits March 24, 2026 09:53
After provisioning completes, users who selected Telegram or Discord are
shown an inline pairing step that polls for incoming pairing requests and
lets them approve with a button. Slack skips this step since it has no
dmPolicy/pairing mechanism.

- New ChannelPairingStep component with channel-specific instructions
- ClawDashboard captures selectedChannelId and routes to pairing step
- ProvisioningStep accepts dynamic totalSteps (4 or 5)
Extract ChannelPairingStepView as a pure visual component (no hooks)
following the ProvisioningStep/ProvisioningStepView pattern. Stories
cover both channels, waiting/request/approving/loading states.
Replace instruction card + dashed polling box with a centered spinner,
heading, and subtitle matching the provisioning step style. Title now
reads 'Pair your Telegram/Discord bot'. Skip button uses subdued
opacity. Step indicator stays left-aligned.
Show pairing code prominently with user ID, full-width authorize
button, and decline link. Remove dead imports and JSX comments.
Add cursor-pointer to all interactive elements.
…h-then-wait

Replaces setInterval(5s) with a sequential loop that waits 1s after
each fetch completes, preventing request pileup on slow responses.
Move the 60-second boot delay from ChannelPairingStep into
ProvisioningStep so the user sees one continuous 'Setting up your
instance' spinner instead of two spinners in sequence. Config
mutations still fire immediately; onComplete is deferred until both
the config is applied and the timer elapses.

Fix the approval flash bug where the UI briefly reverted to the
'waiting for message' state after approving a pairing request. The
mutation's global onSuccess invalidates the pairing query (clearing
matchingRequest) before the call-site onSuccess fires onComplete.
pendingApproval preserves the request data across that refetch window.
Expose the controller's /_kilo/health endpoint (bootstrapping → starting
→ ready → degraded) through the full stack so the frontend can track
machine bootstrap progress. Both ProvisioningStep and ChannelPairingStep
poll every 1s and log the result to the browser console.
Add /_kilo/gateway/ready controller route that fetches /ready from the
OpenClaw gateway at 127.0.0.1:3001 and exposes it through the full
stack. Both ProvisioningStep and ChannelPairingStep now poll both
controller health (/_kilo/health) and gateway ready (/ready) every 1s,
logging both to the browser console for comparison during onboarding.
Return 200 with error details in the body instead of 500 when the
gateway isn't reachable yet. Prevents a wall of errors in the console
and tRPC cache during the bootstrap window.
Wait for the gateway to report ready: true instead of an arbitrary 60s
timeout. Remove console logging from both onboarding steps.
The controller health polling was only needed for debugging. The
gateway /ready endpoint is the one used for the provisioning gate.
@RSO RSO force-pushed the RSO/pond-rugby branch from 9c6eb92 to bd7f419 Compare March 24, 2026 13:21
The /ready endpoint reports readiness before boot CPU pressure subsides.
When the user sends a message immediately after ready: true, the combined
load triggers throttling on the shared-cpu-2x instance.

Add os.loadavg() and a 'settled' boolean to the controller's /ready
response (threshold: 0.1 for ~6% shared CPU allocation), and gate
ProvisioningStep on settled === true so the frontend waits for the
system to actually be idle before advancing.
@RSO RSO changed the title feat(claw): add channel pairing step to onboarding for Telegram/Discord feat(claw): add channel pairing step and load-settled gate to onboarding Mar 24, 2026
@RSO RSO requested a review from a team March 24, 2026 16:06
@RSO RSO marked this pull request as ready for review March 24, 2026 16:06
@kilo-code-bot
Copy link
Copy Markdown
Contributor

kilo-code-bot bot commented Mar 24, 2026

Code Review Summary

Status: 1 Issue Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 1
SUGGESTION 0

Fix these issues in Kilo Cloud

Issue Details (click to expand)

WARNING

File Line Issue
kiloclaw/src/routes/platform.ts 641 The new /gateway/ready endpoint returns raw exception text in a 200 response, which now exposes backend/controller internals directly to the authenticated UI instead of going through the existing sanitization path.
Other Observations (not in diff)

N/A

Files Reviewed (13 files)
  • kiloclaw/controller/src/routes/gateway.ts
  • kiloclaw/src/durable-objects/gateway-controller-types.ts
  • kiloclaw/src/durable-objects/kiloclaw-instance/gateway.ts
  • kiloclaw/src/durable-objects/kiloclaw-instance/index.ts
  • kiloclaw/src/routes/platform.ts - 1 issue
  • src/app/(app)/claw/components/ChannelPairingStep.tsx
  • src/app/(app)/claw/components/ClawDashboard.tsx
  • src/app/(app)/claw/components/ProvisioningStep.tsx
  • src/hooks/useKiloClaw.ts
  • src/lib/kiloclaw/kiloclaw-internal-client.ts
  • src/lib/kiloclaw/types.ts
  • src/routers/kiloclaw-router.ts
  • storybook/stories/claw/ChannelPairingStep.stories.tsx

@kilo-code-bot
Copy link
Copy Markdown
Contributor

kilo-code-bot bot commented Mar 24, 2026

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (5 files)
  • kiloclaw/src/durable-objects/kiloclaw-instance/index.ts
  • kiloclaw/src/routes/platform.ts
  • src/app/(app)/claw/components/ProvisioningStep.tsx
  • src/lib/kiloclaw/kiloclaw-internal-client.ts
  • src/lib/kiloclaw/types.ts

Reviewed by gpt-5.4-20260305 · 1,272,556 tokens

@RSO RSO enabled auto-merge March 25, 2026 07:47
@RSO RSO merged commit 463eb06 into main Mar 25, 2026
19 checks passed
@RSO RSO deleted the RSO/pond-rugby branch March 25, 2026 07:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants